package controleur;

import java.util.ArrayList;

import modele.Graphe;

public class ControleurGraphe {
	// Variable(s) d'instance
	private Graphe graphe;
	
	// Constructeur(s)
	public ControleurGraphe(int nombreUnites) {
		this.graphe=new Graphe(nombreUnites);
		this.initialiser();
	}
	
	public ControleurGraphe(ControleurGraphe graphe) {
		this.graphe=new Graphe(graphe.size());
		for(int i = 0; i < this.size(); i++) {
			for(int j = 0; j < this.size(); j++) {
				this.set(i, j, graphe.get(i, j));
			}
		}
	}
	
	// Methode(s)
	private void initialiser() {
		// On initialise tout le graphe a faux
		for(int i = 0; i < this.size(); i++) {
			for(int j = 0; j < this.size(); j++) {
				this.graphe.getMatrice()[i][j]=false;
			}
		}
	}
	
	public int size() {
		// Retourne la largeur du graphe
		return this.graphe.getMatrice().length;
	}
	
	public boolean get(int i, int j) {
		return this.graphe.getMatrice()[i][j];
	}
	
	public void set(int i, int j, boolean valeur) {
		this.graphe.getMatrice()[i][j]=valeur;
	}
	
	public String toString() {
		// Retourne un string representant le contenu de tout le graphe
		// Utilise lors des tests
		String retour="";
		for(int i = 0; i < this.size(); i++) {
			for(int j = 0; j < this.size(); j++) {
				retour+=this.get(i, j)+"\t";
			}
			retour+="\n";
		}
		return retour;
	}
	
	public ArrayList<Integer> getVoisins(int i) {
		// Retournes les voisins de l'unite i
		ArrayList<Integer> voisins = new ArrayList<Integer>();
		for(int j = 0; j < graphe.getMatrice().length; j++) {
			if(graphe.getMatrice()[i][j]) {
				voisins.add(j);
			}
		}
		return voisins;
	}
	
	public void completer(ControleurPlateau plateau) {
		// Construit le graphe en fonction des unites presentes sur le plateau
		// Si i est sur la fin de trajectoire de j, alors il y a un arc de i a j
		ControleurUnite unite;
		for(int i = 0; i < this.size(); i++) {
			unite = plateau.getUnite(i);
			for(int j = unite.getTrajectoire().getIndiceActuel(); j < unite.getTrajectoire().taille(); j++) {
				if(plateau.getGraphe().get(unite.getTrajectoire().get(j)).getUnitePresente()!=null) {
					if(plateau.getGraphe().get(unite.getTrajectoire().get(j)).getUnitePresente().getLabel()!=i) {
						this.set(plateau.getGraphe().get(unite.getTrajectoire().get(j)).getUnitePresente().getLabel(), i, true);
					}
				}
			}
		}
	}
	
	public void completer(String[][] plateauString, ControleurPlateau plateau) {
		// Construit le graphe en fonction des unites presentes sur le plateau
		// Si i est sur la fin de trajectoire de j, alors il y a un arc de i a j
		ControleurUnite unite;
		for(int i = 0; i < this.size(); i++) {
			unite = plateau.getUnite(i);
			for(int j = unite.getTrajectoire().getIndiceActuel(); j < unite.getTrajectoire().taille(); j++) {
				if(plateauString[unite.getTrajectoire().get(j).getX()][unite.getTrajectoire().get(j).getY()].matches("\\d")) {
					if(!plateauString[unite.getTrajectoire().get(j).getX()][unite.getTrajectoire().get(j).getY()].matches(""+i)) {
						this.set(Integer.parseInt(plateauString[unite.getTrajectoire().get(j).getX()][unite.getTrajectoire().get(j).getY()]), i, true);
					}
				}
			}
		}
	}
	
	public void enleverUnite(int unite) {
		// On enleve tous les arcs impliquant unite
		for(int i = 0; i < this.size(); i++) {
			this.set(unite, i, false);
			this.set(i, unite, false);
		}
	}
	
	public void ajoutUnite(ControleurUnite unite, ControleurPlateau plateau, ControleurGrapheCase graphe) {
		// On ajoute les arcs qu'il faut en fonction de l'unite unite
		ControleurUnite uniteCourante;
		for(int i = 0; i < this.size(); i++) {
			if(i != unite.getLabel()) {
				// Si l'unite courante n'est pas l'unite passee en parametre
				uniteCourante = plateau.getUnite(i);
				for(int l = uniteCourante.getTrajectoire().getIndiceActuel()+1; l < uniteCourante.getTrajectoire().taille(); l++) {
					if(uniteCourante.getTrajectoire().get(l).equals(unite.getTrajectoire().get(unite.getTrajectoire().getIndiceActuel()+1))) {
						this.set(unite.getLabel(), i, true);
					}
				}
				/*if(uniteCourante.getTrajectoire().getTrajectoire().contains(unite.getTrajectoire().get(unite.getTrajectoire().getIndiceActuel()+1))) {
					// Si l'unite courante contient le prochain deplacement de unite
					// Alors on cree un arc entre l'unite courante et unite
					this.set(unite.getLabel(), uniteCourante.getLabel(), true);
				}*/
			} else {
				// Sinon, s'il s'agit de l'unite passee en parametre
				for(int j = unite.getTrajectoire().getIndiceActuel()+1; j < unite.getTrajectoire().taille(); j++) {
					if(graphe.get(unite.getTrajectoire().get(j)).getUnitePresente()!=null) {
						this.set(graphe.get(unite.getTrajectoire().get(j)).getUnitePresente().getLabel(), unite.getLabel(), true);
					}
				}
			}
		}
	}
	
	public void ajoutUnite(ControleurUnite unite, ControleurPlateau plateau, String[][] plateauString) {
		ControleurUnite uniteCourante;
		for(int i = 0; i < this.size(); i++) {
			if(i != unite.getLabel()) {
				uniteCourante = plateau.getUnite(i);
				for(int l = uniteCourante.getTrajectoire().getIndiceActuel()+1; l < uniteCourante.getTrajectoire().taille(); l++) {
					if(uniteCourante.getTrajectoire().get(l).equals(unite.getTrajectoire().get(unite.getTrajectoire().getIndiceActuel()+1))) {
						this.set(unite.getLabel(), i, true);
					}
				}
			} else {
				for(int j = unite.getTrajectoire().getIndiceActuel()+1; j < unite.getTrajectoire().getTrajectoire().size(); j++) {
					if(plateauString[unite.getTrajectoire().get(j).getX()][unite.getTrajectoire().get(j).getY()].matches("\\d")) {
						this.set(Integer.parseInt(plateauString[unite.getTrajectoire().get(j).getX()][unite.getTrajectoire().get(j).getY()]), unite.getLabel(), true);
					}
				}
			}
		}
	}
}
